package com.kevinwu.sqlSession;

import com.kevinwu.pojo.Configuation;

import java.beans.IntrospectionException;
import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.List;

public class DefaultSqlSession implements SqlSession {

    private Configuation configuation;

    public DefaultSqlSession(Configuation configuation) {
        this.configuation = configuation;
    }

    /**
     * 查询所有
     * @param statementId
     * @param params
     * @param <E>
     * @return
     * @throws IllegalAccessException
     * @throws IntrospectionException
     * @throws InstantiationException
     * @throws NoSuchFieldException
     * @throws SQLException
     * @throws InvocationTargetException
     * @throws ClassNotFoundException
     */
    @Override
    public <E> List<E> selectAll(String statementId, Object... params) throws IllegalAccessException, IntrospectionException, InstantiationException, NoSuchFieldException, SQLException, InvocationTargetException, ClassNotFoundException {

        SimpleExecutorImpl simpleExecutor = new SimpleExecutorImpl();
        List<Object> list = simpleExecutor.query(configuation, configuation.getMappedStatementMap().get(statementId), params);

        return (List<E>) list;
    }

    /**
     * 根据条件查询一条记录
     * @param statementId
     * @param params
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws ClassNotFoundException
     * @throws IntrospectionException
     * @throws InstantiationException
     * @throws SQLException
     * @throws InvocationTargetException
     * @throws NoSuchFieldException
     */
    @Override
    public <T> T selectOne(String statementId, Object... params) throws IllegalAccessException, ClassNotFoundException, IntrospectionException, InstantiationException, SQLException, InvocationTargetException, NoSuchFieldException {
        List<Object> objects = selectAll(statementId, params);
        if(objects.size()==1){
            return (T) objects.get(0);
        }else{
            throw new RuntimeException("没有记录或者多条记录！");
        }
    }

    /**
     * dao代理
     * @param mapperClass
     * @param <T>
     * @return
     */
    @Override
    public <T> T getMapper(Class<?> mapperClass) {

        Object proxyInstance = Proxy.newProxyInstance(DefaultSqlSession.class.getClassLoader(), new Class[]{mapperClass}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String methodName = method.getName();
                String className = method.getDeclaringClass().getName();
                String statementId = className+"."+methodName;
                //此处后续进行优化，目前是根据方法名称中的关键字，find为查询  inser 为插入 update为更新 delete 为删除
                if(methodName.indexOf("find")>=0){
                    Type genericReturnType = method.getGenericReturnType();
                    if(genericReturnType instanceof ParameterizedType){
                        List<Object> list = selectAll(statementId, args);
                        return list;
                    }

                    return selectOne(statementId,args);
                }else if(methodName.indexOf("insert")>=0){
                    insert(statementId,args);
                }else if(methodName.indexOf("update")>=0){
                    update(statementId,args);
                }else if(methodName.indexOf("delete")>=0){
                    delete(statementId,args);
                }else{
                    throw new RuntimeException("执行了不支持的方法或者方法名称命名不规范！");
                }
                return null;
            }
        });

        return (T) proxyInstance;
    }

    @Override
    public void insert(String statementId, Object... object) throws ClassNotFoundException, SQLException, IllegalAccessException, NoSuchFieldException {
        SimpleExecutorImpl simpleExecutor = new SimpleExecutorImpl();
        simpleExecutor.executeTest(configuation, configuation.getMappedStatementMap().get(statementId), object);
    }

    @Override
    public void update(String statementId, Object... object) throws ClassNotFoundException, SQLException, IllegalAccessException, NoSuchFieldException {
        SimpleExecutorImpl simpleExecutor = new SimpleExecutorImpl();
        simpleExecutor.executeTest(configuation, configuation.getMappedStatementMap().get(statementId), object);
    }

    @Override
    public void delete(String statementId, Object... object) throws ClassNotFoundException, SQLException, IllegalAccessException, NoSuchFieldException {
        SimpleExecutorImpl simpleExecutor = new SimpleExecutorImpl();
        simpleExecutor.deleteTest(configuation, configuation.getMappedStatementMap().get(statementId), object);
    }
}
